﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using Cesave.DistributedServices.PermisosModule.WindowsHost.Resources;
using Cesave.Domain.Core.Entities;
using Cesave.Domain.PermisosModule.Contracts.Agentes;
using Cesave.Domain.PermisosModule.Entities;
using Cesave.Infrastructure.CrossCutting.Hashing;
using Cesave.Infrastructure.CrossCutting.IoC;
using Infragistics.Win;
using Infragistics.Win.Misc;
using Infragistics.Win.UltraWinGrid;

namespace Cesave.DistributedServices.PermisosModule.WindowsHost.ViewModels.Catalogs.Agentes
{
    public partial class AgentesViewModel
    {
        #region Private properties

        /// <summary>
        /// 
        /// </summary>
        private List<Agente> _agentes;

        /// <summary>
        /// 
        /// </summary>
        private Agente _agente;

        #endregion

        #region Public properties

        /// <summary>
        /// 
        /// </summary>
		public List<Agente> Agentes
		{
			get
			{
				return _agentes;
			}
			private set
			{
				_agentes = value;
				if (_agentes != null)
					RaisePropertyChanged("Agentes");
			}
		}

        /// <summary>
        /// 
        /// </summary>
		public Agente Agente
		{
			get
			{
				return _agente;
			}
			private set
			{
				_agente = value;
				if (_agente != null)
					RaisePropertyChanged("Agente");
			}
		}

        /// <summary>
        /// 
        /// </summary>
        public bool IsAgenteReady
        {
            get
            {
                return Agente != null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsAgenteNew
        {
            get
            {
                return Agente.AgenteGuid == Guid.Empty;
            }
        }

        #endregion

        #region Actions

		/// <summary>
		/// 
		/// </summary>
		private void LoadAgentes()
		{
			StartWaiting();
			using (BackgroundWorker worker = new BackgroundWorker())
			{
				worker.DoWork += (sender, e) =>
				{
					IAgenteService agenteService = IoCFactory.Resolve<IAgenteService>();
					e.Result = agenteService.FindAgentesByJunta(Junta.JuntaGuid);
				};
				worker.RunWorkerCompleted += (sender, e) =>
				{
					EndWaiting();
					if (!e.Cancelled && e.Error == null)
						Agentes = e.Result as List<Agente>;
					else if (e.Error != null)
						MessageBox.Show(
							_agentesView,
							e.Error.Message,
							WindowTitles.AgentesWindowTitle,
							MessageBoxButtons.OK,
							MessageBoxIcon.Error
						);
				};
				worker.WorkerSupportsCancellation = true;
				worker.RunWorkerAsync();
			}
		}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SaveAgente(object sender, EventArgs e)
        {
			if (_agenteView.currentPasswordTextBox.Visible && !string.IsNullOrEmpty(_agenteView.currentPasswordTextBox.Text))
				SetPasswordChangeValidation();
			else
				RemovePasswordChangeValidation();
			if (!string.IsNullOrEmpty(_agenteView.newPasswordTextBox.Text))
				SetNewPasswordValidation();
			else
				RemoveNewPasswordValidation();
			if (_agenteView.validator.Validate().IsValid)
			{
				try
				{
					string currentPassword = _agenteView.currentPasswordTextBox.Text;
					string newPassword = _agenteView.newPasswordTextBox.Text;
					IAgenteService agenteService = IoCFactory.Resolve<IAgenteService>();
					if (Agente.ChangeTracker.State == ObjectState.Added)
					{
						Agente.PasswordHash = newPassword;
						agenteService.AddAgente(Agente);
					}
					else if (Agente.ChangeTracker.State == ObjectState.Modified)
						agenteService.ChangeAgente(Agente);
					CloseAgenteView(sender, e);
					LoadAgentes();
				}
				catch (Exception ex)
				{
					MessageBox.Show(
						_agenteView,
						ex.Message,
						WindowTitles.AgentesWindowTitle,
						MessageBoxButtons.OK,
						MessageBoxIcon.Error
					);
					//};
					//    worker.WorkerSupportsCancellation = true;
					//    worker.RunWorkerAsync();
					//}
				}
				finally
				{
					RemoveNewPasswordValidation();
					RemovePasswordChangeValidation();
					_agenteView.newPasswordTextBox.Text = string.Empty;
					_agenteView.currentPasswordTextBox.Text = string.Empty;
				}
			}
        }

		/// <summary>
		/// 
		/// </summary>
		private void RemoveNewPasswordValidation()
		{
			ValidationSettings validationSettings = _agenteView.validator.GetValidationSettings(_agenteView.newPasswordTextBox);
			validationSettings.Condition = null;
		}

		/// <summary>
		/// 
		/// </summary>
		private void SetNewPasswordValidation()
		{
			string newPassword = _agenteView.newPasswordTextBox.Text;
			string confirmPassword = _agenteView.confirmPasswordTextBox.Text;
			ValidationSettings validationSettings = _agenteView.validator.GetValidationSettings(_agenteView.newPasswordTextBox);
			validationSettings.Condition = new OperatorCondition(ConditionOperator.Equals, confirmPassword, true);
			validationSettings.ValidationTrigger = ValidationTrigger.Programmatic;
			validationSettings.NotificationSettings.Caption = "Contraseña";
			validationSettings.NotificationSettings.Text = "Las contraseñas no coinciden.";
		}

		/// <summary>
		/// 
		/// </summary>
		private void RemovePasswordChangeValidation()
		{
			ValidationSettings validationSettings = _agenteView.validator.GetValidationSettings(_agenteView.currentPasswordTextBox);
			validationSettings.Condition = null;
		}

		/// <summary>
		/// 
		/// </summary>
		private void SetPasswordChangeValidation()
		{
			string currentPassword = _agenteView.currentPasswordTextBox.Text;
			ValidationSettings validationSettings = _agenteView.validator.GetValidationSettings(_agenteView.currentPasswordTextBox);
			validationSettings.ValidationTrigger = ValidationTrigger.Programmatic;
			string currentHash = SaltAndHash.Hash(currentPassword, Agente.PasswordSalt);
			_agenteView.currentPasswordTextBox.Text = currentHash;
			validationSettings.Condition = new OperatorCondition(ConditionOperator.Equals, Agente.PasswordHash);
			validationSettings.NotificationSettings.Caption = "Contraseña incorrecta";
			validationSettings.NotificationSettings.Text = "La contraseña no coincide con la contraseña actual.";
		}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EditAgente(object sender, EventArgs e)
        {
            PrepareAgenteFormToEdit();
			ShowAgenteForm(sender, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddNewAgente(object sender, EventArgs e)
        {
            _agenteView.agenteBindingSource.AddingNew += AddingNewAgente;
            _agenteView.agenteBindingSource.AddNew();
			ShowAgenteForm(sender, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void AddingNewAgente(object sender, AddingNewEventArgs e)
        {
            Agente agente = new Agente
            {
                AclGuid = Acl.AclGuid,
                AclId = Acl.AclId,
                AgenteGuid = Guid.NewGuid(),
                AgenteId = 0,
                Apellido = string.Empty,
                Domicilio = string.Empty,
                Email = string.Empty,
                JuntaGuid = Junta.JuntaGuid,
                JuntaId = Junta.JuntaId,
                Nombre = string.Empty,
                PasswordHash = string.Empty,
                PasswordSalt = string.Empty,
                Status = true,
                Telefono = string.Empty,
                Usuario = string.Empty,
            };
			Agente = agente;
            Agente.MarkAsAdded();
            e.NewObject = Agente;
            FocusDefaultControl();
            PrepareAgenteFormToAdd();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ShowAgenteForm(object sender, EventArgs e)
        {
            _agenteView.saveButton.Click += SaveAgente;
			_agenteView.Show();
        }

        /// <summary>
        /// 
        /// </summary>
        private void PrepareAgenteFormToEdit()
        {
			Agente.MarkAsModified();
            _agenteView.currentPasswordLabel.Visible = _agenteView.currentPasswordTextBox.Visible = true;
            _agenteView.currentPasswordLabel.Text = "Contraseña actual:";
        }

        /// <summary>
        /// 
        /// </summary>
        private void PrepareAgenteFormToAdd()
        {
			_agenteView.currentPasswordLabel.Visible = _agenteView.currentPasswordTextBox.Visible = false;
			_agenteView.passwordHashLabel.Text = "Contraseña:";
        }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void DeleteAgente(object sender, BeforeRowsDeletedEventArgs e)
		{
			e.DisplayPromptMsg = false;
			DialogResult dialogResult = MessageBox.Show(
				_agentesView,
				"¿Está seguro que desea eliminar al agente selecciondo?",
				WindowTitles.AgentesWindowTitle,
				MessageBoxButtons.YesNo,
				MessageBoxIcon.Question
			);
			if (dialogResult == DialogResult.Yes)
				using (BackgroundWorker worker = new BackgroundWorker())
				{
					worker.DoWork += (wSender, wArgs) =>
					{
						IAgenteService agenteService = IoCFactory.Resolve<IAgenteService>();
						agenteService.DeleteAgente(Agente);
					};
					worker.RunWorkerCompleted += (wSender, wArgs) =>
					{
						if (wArgs.Error != null)
							MessageBox.Show(
								_agentesView,
								wArgs.Error.Message,
								WindowTitles.AgentesWindowTitle,
								MessageBoxButtons.OK,
								MessageBoxIcon.Error
							);
					};
					worker.WorkerSupportsCancellation = true;
					worker.RunWorkerAsync();
				}
			else
				e.Cancel = true;
		}

        #endregion

        #region Event methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SetCurrentAgente(object sender, EventArgs e)
        {
            BindingSource bindingSource = sender as BindingSource;
            if (bindingSource != null)
                if (bindingSource.Current != null)
                    Agente = bindingSource.Current as Agente;
        }

        /// <summary>
        /// 
        /// </summary>
        private void OnAgentePropertyChanged()
        {
			Agente.ChangeTracker.State = ObjectState.Modified;
            _agentesView.deleteButton.Enabled = IsAgenteReady;
            _agenteView.agenteBindingSource.DataSource = Agente;
            _agentesView.agentesGrid.DoubleClickRow += EditAgente;
        }

        /// <summary>
        /// 
        /// </summary>
        private void OnAgentesPropertyChanged()
        {
            _agentesView.agentesBindingSource.DataSource = Agentes;
            _agentesView.agentesBindingSource.CurrentChanged += SetCurrentAgente;
            SetCurrentAgente(_agentesView.agentesBindingSource, new EventArgs());
        }

        #endregion
        
    }
}
